//
//  WIFI.cpp
//  WiFi_Config
//
//  Created by 伍阳阳 on 2021/1/7.
//  Copyright © 2021 伍阳阳. All rights reserved.
//

#include "WIFI.hpp"

void WIFI::setLocalWifiName(const char * wifi_ssid){
    local_ssid = wifi_ssid;
}

void WIFI::setLocalWifiPwd(const char * wifi_pwd){
    local_pwd = wifi_pwd;
}

void WIFI::setCallBack(void (*fun)(void)){
    callback = fun;
};

WIFI::WIFI(){
    
    Serial.begin(115200);
    
    //pinMode(PIN_LED, OUTPUT);
    local_ssid = "ap_9";
    local_pwd = "12345678";
    Webserver = new ESP8266WebServer(80);
    dnsServer = new DNSServer;
    
    
}
WIFI::~WIFI(){
    Serial.println("delete....");
    delete Webserver;
    delete dnsServer;
}

void WIFI::loop(){
    Webserver->handleClient();
    dnsServer->processNextRequest();
}


void WIFI::restart(){
    WiFi.disconnect(true);//wifi断开
    delay(100);
    removeCache();
    delay(300);
    ESP.restart(); //重启
    
}
void WIFI::Start(){
     init();
}
void WIFI::Start(const char* ssid,const char* pwd){
    local_ssid = ssid;
    local_pwd = pwd;
    init();
}

//初始化
void WIFI::init(){
    
    types = CONNECT_INIT;
    WiFi.mode(WIFI_AP_STA);//设置模式为ap和混杂模式
    read_ssid();
    
    
}



void WIFI::create_wifi(){
    Serial.println("开始创建wifi");
    
    
    //WiFi.softAP(local_ssid,local_pwd,3,1);//通道3  0wifi隐藏1不隐藏
    WiFi.softAP(local_ssid,local_pwd);//通道3  0wifi隐藏1不隐藏
    IPAddress softLocal(9, 9, 9, 9); //  IP地址
    IPAddress softGateway(9, 9, 9, 9); //网关
    IPAddress softSubnet(255, 255, 255, 0); //子网掩码
    WiFi.softAPConfig(softLocal, softGateway, softSubnet);
    dnsServer->start(DNS_PORT, "*", softLocal);
    Webserver->on("/", [this](void){webview_start();});
    // Webserver->on("/", std::bind(&WIFI::webview_start, this ));
    Webserver->on("/connect", [this](void){webview_connect();});
    Webserver->on("/getList",  [this](void){webview_getlist();});
    Webserver->on("/type",[this](void){
        webview_gettype();
    });
    Webserver->onNotFound([this](void){
        Webserver->send(200, "text/html", "<html><head><title>正在跳转</title></head><body><script language='javascript'>document.location = '/'</script></body></html>");
    });
    Webserver->begin();
    
    
    
}


//连接上了
void WIFI::connect_success(){
    types = CONNECT_OK;
    WiFi.softAPdisconnect(false);
}


//连接wifi
void WIFI::connect_wifi(const char* ssid,const char* pwd){
    
    int ssid_length = strlen(ssid);
    int pwd_length  = strlen(pwd);
    if(ssid_length>0&& ssid_length < 33 &&pwd_length>7&& pwd_length<65){
        WiFi.begin(ssid, pwd);
        unsigned long millis_time = millis();
        while ((WiFi.status() != WL_CONNECTED) && (millis() - millis_time < 10000))
        {
            delay(500);
            Serial.print(".");
        }
        if(WiFi.status() == WL_CONNECTED){
            //连接成功
            save_ssid(ssid,pwd);
            types = CONNECT_SUCCESS;
            
            WiFi.softAPdisconnect();
            if(callback!=NULL){
                
                callback();
            }
            
        }else{
            //连接失败
            types = CONNECT_FAIL;
            
        }
        
        
    }else{
        types = CONNECT_FAIL;
        
    }
    
}
//读取wifi名称
void WIFI::read_ssid(){
    File datafile =  readCache();
    if(datafile.size() <= 0){
        //没有wifi存储的 进行创建热点和开启监听网络
        types = CONNECT_NOSSID;
        create_wifi();
    }else{
        String data;
        for (int i = 0; i < datafile.size(); i++) {
            data.concat(String((char)datafile.read()));
        }
        datafile.close();
        
        StaticJsonDocument<200> doc;
        deserializeJson(doc, data);
        const char* ssid = doc["ssid"];
        const char* pwd = doc["pwd"];
        Serial.println("ssid pwd :");
        Serial.println(ssid);
        Serial.println(pwd);
        types = CONNECT_LOADING;
        
        connect_wifi(ssid,pwd);
    }
}

//保存wifi
void WIFI::save_ssid(const char* ssid,const char* pwd){
    StaticJsonDocument<200> jsonBuffer;
    jsonBuffer["ssid"] = ssid;
    jsonBuffer["pwd"] = pwd;
    String data_save;
    serializeJsonPretty(jsonBuffer, data_save);
    Serial.println("保存了... ");
    Serial.println(data_save);
    saveCache(data_save.c_str());
}


//读取闪存文件
File WIFI::readCache() {
    if (LittleFS.begin()) { // 启动闪存文件系统
        Serial.println("LittleFS Started.");
    } else {
        Serial.println("LittleFS Failed to Start.");
    }
    File dataFile;
    //确认闪存中是否有file_name文件
    if (LittleFS.exists(file_name)) {
        Serial.print(file_name);
        //建立File对象用于从LittleFS中读取文件
        dataFile = LittleFS.open(file_name, "r");
        return dataFile;
    } else {
        
        return dataFile;
    }
}


//保存文件到闪存
void WIFI::saveCache(const char* data) {
    //LittleFS.format();    // 格式化LittleFS
    if (LittleFS.begin()) { // 启动LittleFS
        Serial.println("LittleFS Started.");
    } else {
        Serial.println("LittleFS Failed to Start.");
    }
    File dataFile = LittleFS.open(file_name, "w");
    dataFile.println(data);       // 向dataFile写入字符串信息
    Serial.println("写入" + String(data) + "完成!");
    dataFile.close();
}
void WIFI::removeCache(){
    if (LittleFS.begin()) { // 启动LittleFS
        Serial.println("LittleFS Started.");
    } else {
        Serial.println("LittleFS Failed to Start.");
    }
    LittleFS.format();
    
    types = CONNECT_NOSSID;
    
}



//未连接网络的时候的led灯
void WIFI::noled(){
    digitalWrite(PIN_LED, 0);
    delay(500);
    digitalWrite(PIN_LED, 1);
    delay(500);
}

void WIFI::connect_loading_led(){
    
    digitalWrite(PIN_LED, 0);
};
void WIFI::connect_success_led(){
    
    
    digitalWrite(PIN_LED, 1);
    
}

String WIFI::wifi_type(int typecode)
{
    if (typecode == ENC_TYPE_NONE) return "开放网络";//Open
    if (typecode == ENC_TYPE_WEP) return "加密网络"; //WEP  Wired Equivalent Privacy，有线等效保密
    if (typecode == ENC_TYPE_TKIP) return "加密网络";//WPA WiFi网络安全存取
    if (typecode == ENC_TYPE_CCMP) return "加密网络";//WPA2 即WPA加密的升级版
    if (typecode == ENC_TYPE_AUTO) return "加密网络";//加密 WPA*
}

void WIFI::webview_start(){
    
    Serial.println("打印了wifi页面....");
    
    Webserver->send(200, "text/html", webs_html.c_str());
    
}
void WIFI::webview_connect(){
    
    const char* names = Webserver->arg("ssid").c_str();
    const char* pwd = Webserver->arg("password").c_str();
    Serial.println("传入的: ");
    Serial.println(names);
    Serial.println(pwd);
    types = CONNECT_LOADING;
    Serial.println("into connect....");
    Webserver->send(200, "text/json;charset=UTF-8", "{\"code\":\"200\",\"response\":\"连接中...\"}");
    connect_wifi(names,pwd);
    
    
}

void WIFI::webview_gettype(){
    
    if(types == CONNECT_LOADING){
        Serial.println("连接中...");
        Webserver->send(200, "text/json;charset=UTF-8", "{\"code\":\"300\",\"response\":\"连接中...\"}");
        
    }else if(types == CONNECT_SUCCESS){
        Serial.println("连接完成...");
        Webserver->send(200, "text/json;charset=UTF-8", "{\"code\":\"200\",\"response\":\"连接成功了\"}");
    }else if(types == CONNECT_FAIL){
        Serial.println("连接失败...");
        Webserver->send(200, "text/json;charset=UTF-8", "{\"code\":\"400\",\"response\":\"连接失败了\"}");
    }
}

void WIFI::webview_getlist(){
    WiFi.scanNetworksAsync([this](int n){
        
        String req_json = "";
        if (n > 0)
        {
            int m = 0;
            req_json = "{\"code\":\"200\",\"response\":[";
            for (int i = 0; i < n; i++)
            {
                if ((int)WiFi.RSSI(i) >= -200)
                {
                    m++;
                    String a="{\"ssid\":\"" + (String)WiFi.SSID(i) + "\"," + "\"type\":\"" + wifi_type(WiFi.encryptionType(i)) + "\"" +  "},";
                    if(a.length()>15)
                        req_json += a;
                }
            }
            req_json.remove(req_json.length() - 1);
            req_json += "]}";
            Serial.println("发送列表wifi...");
            Webserver->send(200, "text/json;charset=UTF-8", req_json);
            
        }
        
        
    },IS_SHOW_HIDE_WIFI);
}

//状态
void WIFI::onEvent(){
    switch (types) {
        case CONNECT_INIT:
            Serial.println("初始化...");
            noled();
            break;
        case CONNECT_NOSSID:
            Serial.println("未找到存储的密码");
            noled();
            //创建ap网络和端口
            break;
        case CONNECT_LOADING:
            Serial.println("连接wifi中....");
            connect_loading_led();
            break;
        case CONNECT_SUCCESS:
            Serial.println("连接wifi成功....");
            connect_success_led();
            connect_success();
            break;
        case CONNECT_FAIL:
            Serial.println("连接wifi失败....");
            removeCache();
            break;
        case CONNECT_OK:
            Serial.println("OK");
            if(WiFi.status()!=WL_CONNECTED){
                types = CONNECT_FAIL;
            }
            break;
        default:
            break;
    }
}
